package Simplification;

import java.util.LinkedHashSet;
import java.util.LinkedList;

import Syntaxe.Expression;
import Syntaxe.Fraction;
import Syntaxe.Invariant;
import Syntaxe.Matrice;

public class PreSimplification {
	// assort variables if assumtion of inv not verified

		
	Matrice a ;
	Fraction[] b ;
	public LinkedHashSet<String> SetVar;

	public PreSimplification(Invariant inv,LinkedHashSet<String> set) {
		SetVar=set;
		 a = MatriceA(inv);
		 b = b(inv);
	}
	
	public Matrice MatriceA(Invariant inv) { // Ax>=b

		int M = inv.numExpr;
		int N = inv.numVar(); // numbre de variable
		Matrice m = new Matrice(M, N);

		LinkedList<Expression> list = inv.listExpr;
		int i = 0;
		int j = 0;
		LinkedList<String> Var = new LinkedList<String>(); // ??????
		while (!list.isEmpty()) {
			Expression expr = list.poll();

			for (String s : this.SetVar) {
				m.matrice[i][j] = expr.subList.get(s);
				j++;
			}
			// m.matrice[i][j]= expr.constantOfExpression;
			i++;
		}
		return m;
	}

	public Fraction[] b(Invariant inv) { // Ax>=b
		int M = inv.numExpr;
		Fraction[] b = new Fraction[M];
		int i = 0;
		LinkedList<Expression> list = inv.listExpr;
		while (!list.isEmpty()) {
			Expression expr = list.poll();
			// TODO
			b[i] = expr.constantOfExpression.multiple(-1);
			// 要不要乘-1？？
			i++;
		}
		return b;
	}
	public PreSimplification(Matrice m) {
		int M=m.M;
		int N=m.N;
		a = m.subColonne(0, N-2);
		b=new Fraction[M];
		 for (int i=0;i<M;i++){
			 b[i]=m.matrice[i][N-1];
		 }
	}

	public Matrice standard() {
		// from Ax>=b
		// to Ax=b, b>=0, x>=0
		
		// new system: Ax1-Ax2-Z=b, x1>=0,x2>=0,Z>=0
		int M = a.M;
		int N = a.N * 2 + M;
		
		Matrice I = Matrice.eye(M);
		
		Matrice matrice = Matrice.fusion(a, a.MultiNum(-1));
		//matrice.AfficheMatrice();
		matrice = Matrice.fusion(matrice, I.MultiNum(-1));
		//matrice.AfficheMatrice();
		matrice = Matrice.fusion(matrice, b);
		//matrice.AfficheMatrice();
		// to get b>=0
		for (int i = 0; i < M; i++) {
			if (b[i].strictNegative()) {
				matrice.MultiLigne(i, -1);
			}
		}
		return matrice;
	}
	
	public Fraction[] foncExtend(Fraction[] f) {
		// la fonction que on utiliser apres
		// different que probleme reel
		int N=a.N;
		int M=a.M;
		Fraction[] ans=new Fraction[N * 2 + M];
		for (int i=0;i<N;i++)
		{
			ans[i]=f[i];
		}	
		for (int i=0;i<N;i++)
		{
			ans[i+N]=f[i].multiple(-1);
		}
		for (int i=0;i<M;i++)
		{
			ans[i+N*2]=new Fraction(0);
		}
		return ans;
	}

	public void firstStep() {
		// TODO
	}

}
